#include "ds3231_rtc.h"
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "hardware/gpio.h"
#include "FreeRTOS.h"
#include "task.h"
#include "LOG.h"
#include <stdio.h>
#include <string.h>
#include "board.h"
#include "ht1621b.h"  // 添加HT1621B头文件以控制冒号显示

static ds3231_int_callback_t ds3231_int_callback = NULL;

// BCD转十进制
static uint8_t bcd_to_dec(uint8_t val) {
    return (val >> 4) * 10 + (val & 0x0F);
}

// 十进制转BCD
static uint8_t dec_to_bcd(uint8_t val) {
    return ((val / 10) << 4) + (val % 10);
}

// DS3231中断处理函数
static void ds3231_irq_handler(uint gpio, uint32_t events) {
    // 检查是否是DS3231的中断引脚
    if (gpio == DS3231_INT_PIN) {
        // 调用注册的回调函数
        if (ds3231_int_callback != NULL) {
            ds3231_int_callback();
        }
    }
}

// 读取DS3231控制寄存器
static bool ds3231_read_control(uint8_t *control_reg) {
    uint8_t reg_addr = DS3231_REG_CONTROL;
    
    // 写入寄存器地址
    int ret = i2c_write_blocking(DS3231_I2C, DS3231_I2C_ADDR, &reg_addr, 1, true);
    if (ret < 0) {
        LOG_ERROR("ds3231_read_control - Failed to write register address");
        return false;
    }
    
    // 读取控制寄存器值
    ret = i2c_read_blocking(DS3231_I2C, DS3231_I2C_ADDR, control_reg, 1, false);
    if (ret < 0) {
        LOG_ERROR("ds3231_read_control - Failed to read control register");
        return false;
    }
    
    return true;
}

// 写入DS3231控制寄存器
static bool ds3231_write_control(uint8_t control_reg) {
    uint8_t data[2];
    data[0] = DS3231_REG_CONTROL;
    data[1] = control_reg;
    
    int ret = i2c_write_blocking(DS3231_I2C, DS3231_I2C_ADDR, data, 2, false);
    if (ret < 0) {
        LOG_ERROR("ds3231_write_control - Failed to write control register");
        return false;
    }
    
    return true;
}

// 读取DS3231状态寄存器
static bool ds3231_read_status(uint8_t *status_reg) {
    uint8_t reg_addr = DS3231_REG_STATUS;
    
    // 写入寄存器地址
    int ret = i2c_write_blocking(DS3231_I2C, DS3231_I2C_ADDR, &reg_addr, 1, true);
    if (ret < 0) {
        LOG_ERROR("ds3231_read_status - Failed to write register address");
        return false;
    }
    
    // 读取状态寄存器值
    ret = i2c_read_blocking(DS3231_I2C, DS3231_I2C_ADDR, status_reg, 1, false);
    if (ret < 0) {
        LOG_ERROR("ds3231_read_status - Failed to read status register");
        return false;
    }
    
    return true;
}

// 写入DS3231状态寄存器
static bool ds3231_write_status(uint8_t status_reg) {
    uint8_t data[2];
    data[0] = DS3231_REG_STATUS;
    data[1] = status_reg;
    
    int ret = i2c_write_blocking(DS3231_I2C, DS3231_I2C_ADDR, data, 2, false);
    if (ret < 0) {
        LOG_ERROR("ds3231_write_status - Failed to write status register");
        return false;
    }
    
    return true;
}

// DS3231 RTC初始化
bool ds3231_rtc_init(void) {
    LOG_INFO("ds3231_rtc_init - Initializing DS3231 RTC");
    
    // 初始化I2C
    LOG_INFO("  - Initializing I2C0 (SDA=%d, SCL=%d)", DS3231_SDA_PIN, DS3231_SCL_PIN);
    i2c_init(DS3231_I2C, 100 * 1000);  // 100kHz
    gpio_set_function(DS3231_SDA_PIN, GPIO_FUNC_I2C);
    gpio_set_function(DS3231_SCL_PIN, GPIO_FUNC_I2C);
    gpio_pull_up(DS3231_SDA_PIN);
    gpio_pull_up(DS3231_SCL_PIN);
    
    // 初始化复位引脚
    LOG_INFO("  - Initializing RST pin %d as output", DS3231_RST_PIN);
    gpio_init(DS3231_RST_PIN);
    gpio_set_dir(DS3231_RST_PIN, GPIO_OUT);
    gpio_put(DS3231_RST_PIN, 1);  // 默认高电平
    
    // 初始化中断引脚（输入）
    LOG_INFO("  - Initializing INT pin %d as input with pull-up", DS3231_INT_PIN);
    gpio_init(DS3231_INT_PIN);
    gpio_set_dir(DS3231_INT_PIN, GPIO_IN);
    gpio_pull_up(DS3231_INT_PIN);
    
    // 配置DS3231输出32kHz时钟信号
    LOG_INFO("  - Configuring DS3231 to output 32kHz clock signal");
    uint8_t status_reg;
    if (!ds3231_read_status(&status_reg)) {
        LOG_ERROR("Failed to read status register");
        return false;
    }
    
    // 设置状态寄存器的BIT3 (EN32KHZ) 为1，启用32kHz输出
    status_reg |= (1 << 3);
    
    if (!ds3231_write_status(status_reg)) {
        LOG_ERROR("Failed to write status register");
        return false;
    }
    
    LOG_INFO("  - DS3231 32kHz output enabled (status register: 0x%02X)", status_reg);
        
    // 设置中断回调
    gpio_set_irq_enabled_with_callback(DS3231_INT_PIN, GPIO_IRQ_EDGE_FALL, true, &ds3231_irq_handler);

    LOG_INFO("ds3231_rtc_init completed successfully");
    return true;
}

// 从DS3231读取时间
bool ds3231_get_time(rtc_time_t *time) {
    if (!time) {
        LOG_ERROR("ds3231_get_time - Invalid parameter");
        return false;
    }
    
    uint8_t reg_addr = DS3231_REG_SECONDS;
    uint8_t data[7];
    
    // 写入起始寄存器地址
    int ret = i2c_write_blocking(DS3231_I2C, DS3231_I2C_ADDR, &reg_addr, 1, true);
    if (ret < 0) {
        LOG_ERROR("ds3231_get_time - Failed to write register address");
        return false;
    }
    
    // 读取时间数据
    ret = i2c_read_blocking(DS3231_I2C, DS3231_I2C_ADDR, data, 7, false);
    if (ret < 0) {
        LOG_ERROR("ds3231_get_time - Failed to read time data");
        return false;
    }
    
    // 转换BCD为十进制
    time->seconds = bcd_to_dec(data[0] & 0x7F);  // 屏蔽CH位
    time->minutes = bcd_to_dec(data[1]);
    time->hours = bcd_to_dec(data[2] & 0x3F);    // 屏蔽12/24小时位
    time->weekday = bcd_to_dec(data[3]);
    time->date = bcd_to_dec(data[4]);
    time->month = bcd_to_dec(data[5] & 0x1F);    // 屏蔽世纪位
    time->year = bcd_to_dec(data[6]);
    
    return true;
}

// 设置DS3231时间
bool ds3231_set_time(const rtc_time_t *time) {
    if (!time) {
        LOG_ERROR("ds3231_set_time - Invalid parameter");
        return false;
    }
    
    uint8_t data[8];
    data[0] = DS3231_REG_SECONDS;  // 起始寄存器地址
    data[1] = dec_to_bcd(time->seconds);
    data[2] = dec_to_bcd(time->minutes);
    data[3] = dec_to_bcd(time->hours);
    data[4] = dec_to_bcd(time->weekday);
    data[5] = dec_to_bcd(time->date);
    data[6] = dec_to_bcd(time->month);
    data[7] = dec_to_bcd(time->year);
    
    int ret = i2c_write_blocking(DS3231_I2C, DS3231_I2C_ADDR, data, 8, false);
    if (ret < 0) {
        LOG_ERROR("ds3231_set_time - Failed to write time data");
        return false;
    }
    
    return true;
}

void ds3231_callback_register(void (*callback)(void))
{
    ds3231_int_callback = callback;
}
